import { BaseState, StateMachine } from "../module/fsm/fsm";
import { FlashDamageBuff, Effect, EffectMethod } from "./BuffManager";
import Unit from "./Unit";

export const UnitStateEnum = {
    Attack: 'Attack',
    FindAim: 'FindAim',
    Idle: 'Idle',
    MoveToAim: 'MoveToAim',
    Death: 'Death',
}

export class UnitState extends BaseState<Unit>{
    public fsm: UnitStateMachine;
    public constructor(fsm: UnitStateMachine) {
        super();
        this.fsm = fsm;
    }
    public onEnter(...args) {
    }
    public onUpdate(dt: any) {
    }
    public onQuit() {
    }

}

export class AttackState extends UnitState {
    public buff: FlashDamageBuff;
    public count: number = 0;
    public qianyao: number = 0.1;
    public canPlay = true;
    public onEnter() {
        this.count = 0;
        this.buff = new FlashDamageBuff();
        this.buff.fromUnit = this.fsm.Onwer;
        this.buff.targatUnit = this.fsm.aim;

        this.buff.effect = new Effect();
        this.buff.effect.method = EffectMethod.Reduce;
        this.buff.effect.data = {
            currentHp: this.fsm.Onwer.getProperty('atk'),
        }

    }
    public onUpdate() {
        let attackTimeing = this.count / this.fsm.Onwer.getProperty('atk_speed');
        if (this.fsm.CurrentStateTime >= attackTimeing) {
            let self = this.fsm.Onwer;

            if (!this.fsm.aim.isDeath()) {
                let direction = self.pos.sub(this.fsm.aim.pos);
                let distance = direction.len();
                let attackDistance = self.getProperty('atk_range');
                if (distance > attackDistance) {
                    self.changeState(UnitStateEnum.MoveToAim);
                    return;
                }
                if (this.canPlay) {
                    self.anim.play(UnitStateEnum.Attack);
                    console.log('play');
                    this.canPlay = false;
                }
                if (this.fsm.CurrentStateTime >= attackTimeing + this.qianyao) {
                    console.log('addBuff');
                    this.fsm.aim.buffManager.addBuff(this.buff);
                    this.canPlay = true;
                    ++this.count;
                }
            } else {
                self.changeState(UnitStateEnum.FindAim);
            }
        }

    }
}
export class FindAim extends UnitState {
    public onEnter() {
        let self = this.fsm.Onwer;
        this.fsm.aim = self.world.getNearestUnit(self);
        if (this.fsm.aim) {
            self.changeState(UnitStateEnum.Attack);
        } else {
            self.changeState(UnitStateEnum.Idle);
        }
    }
}
export class IdeState extends UnitState {

}
export class MoveToAim extends UnitState {
    aimpos: cc.Vec2
    public onEnter() {
        let self = this.fsm.Onwer;
        this.aimpos = this.fsm.aim.pos;
        self.moveComponent.move(Math.round(this.aimpos.x), Math.round(this.aimpos.y));
    }
    public onUpdate() {
        if (this.fsm.aim.isDeath()) {
            this.fsm.Onwer.changeState(UnitStateEnum.FindAim);
            return;
        }
        let self = this.fsm.Onwer;
        let attackDistance = self.getProperty('atk_range');
        let distance = this.aimpos.sub(this.fsm.aim.pos).len();
        let direction = self.pos.sub(this.fsm.aim.pos);
        if (distance > attackDistance) {

            this.aimpos = this.fsm.aim.pos;
            self.moveComponent.move(Math.round(this.aimpos.x), Math.round(this.aimpos.y));
        }

        if (direction.len() <= attackDistance) {


            self.changeState(UnitStateEnum.Attack);
        }
    }
    public onQuit() {
        this.fsm.Onwer.moveComponent.canelMove();
    }
}
export class DeathState extends UnitState {
    public onEnter() {
        
        this.fsm.Onwer.clear();
    }
}
//let statetype = { AttackState, IdeState, DeathState, FindAim }
export default class UnitStateMachine extends StateMachine<Unit>{

    //public aims: Unit[] = [];

    public aim: Unit = null;
    constructor(owner: Unit) {
        super();
        this.Onwer = owner;
        this.Onwer.fsm = this;
        this.states.set(UnitStateEnum.MoveToAim, new MoveToAim(this));
        this.states.set(UnitStateEnum.Attack, new AttackState(this));
        this.states.set(UnitStateEnum.Idle, new IdeState(this));
        this.states.set(UnitStateEnum.Death, new DeathState(this));
        this.states.set(UnitStateEnum.FindAim, new FindAim(this));
    }

    public stop(){
        super.stop();
        this.aim = null;
    }
}